package lee;

/**
 * 由于前面已经将Hello.java编译好了，放在了out目录下，因此，这里可以不用再编译Hello.java了，使用-classpath指定Hello.class的目录
 * <p>编译：javac -encoding UTF-8 -classpath out -d out src/lee/HelloTest.java src/lee/sub/Apple.java
 * 也可以再全部编译一次
 * <p>编译：javac -encoding UTF-8 -d out src/lee/*.java src/lee/sub/Apple.java
 * <p>运行：java -classpath out lee.HelloTest
 * <p>
 * 正如前面看到的，如果需要使用不同包中的其他类时，总是需要使用该类的全名，这是一件很烦琐的事情。
 * <p>
 * 为了简化编程，Java引入了import关键字，import可以向某个Java文件中导入指定包层次下某个类或全部类，
 * import语句应该出现在package语句（如果有的话）之后、类定义之前。
 * 一个Java源文件只能包含一个package语句，但可以包含多个import语句，多个import语句用于导入多个包层次下的类。
 * 使用import语句导入单个类的用法如下：
 * import package.subpackage...ClassName;
 */
// 上面语句用于直接导入指定Java类。例如导入前面提到的lee.sub.Apple类，应该使用下面的代码：

import lee.sub.Apple;

/**
 * 使用import语句导入指定包下全部类的用法如下：
 * import package.subpackage...*;
 * 上面import语句中的星号（*）只能代表类，不能代表包。
 * 因此使用import lee.*；语句时，它表明导入lee包下的所有类，即Hello类和HelloTest类，而lee包下sub子包内的类则不会被导入。
 * 如需导入lee.sub.Apple类，则可以使用import lee.sub.*；语句来导入lee.sub包下的所有类。
 * <p>
 * 注意：Java默认为所有源文件导入java.lang包下的所有类，
 * 因此前面在Java程序中使用String、System类时都无须使用import语句来导入这些类。
 * 但对于前面介绍数组时提到的Arrays类，其位于java.util包下，则必须使用import语句来导入该类。
 */

/**
 * 在一些极端的情况下，import语句也帮不了我们，此时只能在源文件中使用类全名。
 * 例如，需要在程序中使用java.sql包下的类，也需要使用java.util包下的类，则可以使用如下两行import语句：
 * import java.sql.*;
 * import java.util.*;
 * 如果接下来在程序中需要使用Date类，则会引起如下编译错误：
 * 代码中使用了Date类，而import语句导入的java.sql和java.util包下都包含了Date类，系统糊涂了！
 */
import java.sql.*;
import java.util.*;

/**
 * import语句可以简化编程，可以导入指定包下某个类或全部类。
 * JDK 1.5以后更是增加了一种静态导入的语法，它用于导入指定类的某个静态成员变量、方法或全部的静态成员变量、方法。
 * 静态导入使用import static语句，静态导入也有两种语法，分别用于导入指定类的单个静态成员变量、方法和全部静态成员变量、方法，其中导入指定类的单个静态成员变量、方法的语法格式如下：
 * import static package.subpackage...ClassName.fieldName|methodName;
 * 上面语法导入package.subpackage...ClassName类中名为fieldName的静态成员变量或者名为methodName的静态方法。例如，可以使用import staticjava.lang.System.out；语句来导入java.lang.System类的out静态成员变量。
 */
import static java.lang.System.out;

/**
 * 导入指定类的全部静态成员变量、方法的语法格式如下：
 * import static package.subpackage...ClassName.*;
 * 上面语法中的星号只能代表静态成员变量或方法名。
 * import static语句也放在Java源文件的package语句（如果有的话）之后、类定义之前，
 * 即放在与普通import语句相同的位置，而且import语句和import static语句之间没有任何顺序要求。
 * 用一句话来归纳import和import static的作用：使用import可以省略写包名；而使用import static则可以连类名都省略。
 */
import static java.lang.Math.*;

/**
 * 从上面程序不难看出，import和import static的功能非常相似，只是它们导入的对象不一样而已。
 * import语句和import static语句都是用于减少程序中代码编写量的。
 * 现在可以总结出Java源文件的大体结构如下：
 * <pre>
 *     package 语句       // 0个或1个，必须放在文件开始
 *     import | import static 语句        // 0个或多个，必须放在所有类定义之前
 *     public classDefinition | interfaceDefinition | enumDefinition    // 0个或1个public类、接口或枚举定义
 *     classDefinition | interfaceDefinition | enumDefinition   // 0个或多个普通类、接口或枚举定义
 * </pre>
 * 上面提到了接口定义、枚举定义，可以暂时把接口、枚举都当成一种特殊的类。
 */

public class HelloTest {
    public static void samePackageTest() {
        // 可以直接访问同一个包下的其他类，无需添加前缀
        Hello h = new Hello();
    }

    public static void subPackageTest() {
        // 没有import的情况下 必须写成完整包路径加类名：lee.sub.Apple。
        lee.sub.Apple apple = new lee.sub.Apple();
    }

    public static void importTest() {
        // 由于上面使用import lee.sub.Apple;导入了Apple类，因此这里可以直接使用，不需要再加前缀
        Apple apple = new Apple();
    }

    public static void importAllTest() {
        // 为了让引用更加明确，即使使用了import语句，也还是需要使用类的全名
        java.sql.Date date = new java.sql.Date(1589253564);
    }

    public static void importStaticTest() {
        out.println("import static java.lang.System.out");
    }

    public static void importStaticAllTest() {
        out.println("sqrt(256): " + sqrt(256));
    }

    public static void main(String[] args) {
        samePackageTest();
        subPackageTest();
        importTest();
        importAllTest();
        importStaticTest();
        importStaticAllTest();
    }
}
